Search the index case-insensitively
authorAlex Crichton <alex@alexcrichton.com>
Wed, 21 Jan 2015 20:24:34 +0000 (12:24 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 21 Jan 2015 20:24:34 +0000 (12:24 -0800)
All crates published will enter the index in an all-lowercase fashion. This is
done because the index may be checked out on case-insensitive filesystems and
its integrity needs to be preserved. When looking for a file in the index, a
crate's name is transformed to all lowercase, but the mentioned name in the
index is verified against the name queried to ensure that they match.

Closes rust-lang/crates.io#93
cc rust-lang/crates.io-index#1

src/cargo/sources/registry.rs

index 3652da4a3f44137642b6f64941cf26bf420c4c16..6f0542f9426e12b67a58f5206c83cc36e0863eae 100644 (file)
@@ -363,13 +363,14 @@ impl<'a, 'b> RegistrySource<'a, 'b> {
         }
         // see module comment for why this is structured the way it is
         let path = self.checkout_path.clone();
-        let path = match name.len() {
-            1 => path.join("1").join(name),
-            2 => path.join("2").join(name),
-            3 => path.join("3").join(name.slice_to(1)).join(name),
-            _ => path.join(name.slice(0, 2))
-                     .join(name.slice(2, 4))
-                     .join(name),
+        let fs_name = name.chars().map(|c| c.to_lowercase()).collect::<String>();
+        let path = match fs_name.len() {
+            1 => path.join("1").join(fs_name),
+            2 => path.join("2").join(fs_name),
+            3 => path.join("3").join(fs_name.slice_to(1)).join(fs_name),
+            _ => path.join(fs_name.slice(0, 2))
+                     .join(fs_name.slice(2, 4))
+                     .join(fs_name),
         };
         let summaries = match File::open(&path) {
             Ok(mut f) => {
@@ -385,6 +386,9 @@ impl<'a, 'b> RegistrySource<'a, 'b> {
             }
             Err(..) => Vec::new(),
         };
+        let summaries = summaries.into_iter().filter(|summary| {
+            summary.0.get_package_id().get_name() == name
+        }).collect();
         self.cache.insert(name.to_string(), summaries);
         Ok(self.cache.get(name).unwrap())
     }